package com.wchat.serviceimpl;

import com.lly835.bestpay.service.BestPayService;
import com.wchat.converter.OrderMaster2OrderDtoVConverter;
import com.wchat.dataobject.OrderDetail;
import com.wchat.dataobject.OrderMaster;
import com.wchat.dataobject.ProductInfo;
import com.wchat.dto.CartDto;
import com.wchat.dto.OrderDto;
import com.wchat.enums.OrderStatusEnum;
import com.wchat.enums.PayStatusEnum;
import com.wchat.enums.ResultEnum;
import com.wchat.exceptions.SellException;
import com.wchat.repository.OrderDetailRepository;
import com.wchat.repository.OrderMasterRepository;
import com.wchat.repository.ProductInfoRepository;
import com.wchat.service.OrderService;
import com.wchat.service.PayService;
import com.wchat.service.ProductService;
import com.wchat.utils.JsonUtils;
import com.wchat.utils.KeyUtil;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.transaction.Transactional;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by yangtianrui on 17/8/11.
 */
@Service
public class OrderServiceImpl implements OrderService {
    private static final Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class);

    @Autowired
    private ProductService productService;
    @Autowired
    private OrderDetailRepository orderDetailRepository;
    @Autowired
    private OrderService orderService;
    @Autowired
    private OrderMasterRepository orderMasterRepository;
    @Autowired
    private PayService payService;
    /**
     * 创建订单
     * @param orderDto
     * @return
     */
    @Override
    @Transactional
    public OrderDto create(OrderDto orderDto) {
        //  用户在下单时候就已经生成的订单号
        String orderId = KeyUtil.genUniqueKey();
        //  下单总金额
        BigDecimal orderAmount = new BigDecimal(BigInteger.ZERO);  //  amount
        //  1. 查询商品信息 创建订单第一步 (通过遍历出用户购买了多少中商品 就相当于查看购物车里面哪些商品 商品id 购买数量)
       for(OrderDetail orderDetail:orderDto.getOrderDetails())
       {
          // logger.error("[商品详情]orderdetail{}",orderDetail);
           ProductInfo productInfo = productService.findOne(orderDetail.getProductId());
           if(productInfo == null)
           {
               throw new SellException(ResultEnum.PRODUCT_NOT_EXITS);//  商品不存在
           }
           //  2. 计算总价
            orderAmount = productInfo.getProductPrice()
                    .multiply(new BigDecimal(orderDetail.getProductQuantity()))
                    .add(orderAmount);
           // 3. 订单详情入库
           BeanUtils.copyProperties(productInfo,orderDetail);
           orderDetail.setDetailId(KeyUtil.genUniqueKey());
           orderDetail.setOrderId(orderId);//  订单id
           orderDetail.setCreateTime(new Date());
           orderDetail.setUpdateTime(new Date());
           orderDetailRepository.save(orderDetail);
       }
        OrderMaster orderMaster = new OrderMaster();
        BeanUtils.copyProperties(orderDto,orderMaster);
        orderMaster.setOrderAmount(orderAmount);
        orderMaster.setOrderStatus(OrderStatusEnum.NEW.getCode());
        orderMaster.setPayStatus(PayStatusEnum.SUCCESS.getCode());// TODO: 17/8/12
        orderMaster.setCreateTime(new Date());
        orderMaster.setUpdateTime(new Date());
        orderMaster.setOrderId(orderId);
        orderDto.setOrderId(orderId);
        orderMasterRepository.save(orderMaster); //  写入数据库
        //  计算对应的购物车中添加了多少商品和 注意:在添加傻商品到购物车是不应该扣减库存的 只有等里用户这正式的下单后
        List<CartDto> cartDtoList = orderDto.getOrderDetails().stream().map(e -> new CartDto(e.getProductId()
                ,e.getProductQuantity())).collect(Collectors.toList());
        //  扣减库存
        productService.decreseStock(cartDtoList);
        return orderDto;
    }

    /**
     * 查询单条订单
     * @param orderId 订单号
     * @return 订单信息
     */
    @Override
    @Transactional
    public OrderDto findOne(String orderId) {
        // 查询出订单详情  通过订单id 来获取该订单下的所有商品详情
        List<OrderDetail> orderDetailList = orderDetailRepository.findByOrderId(orderId);
        if(CollectionUtils.isEmpty(orderDetailList))
        {
            throw new SellException(ResultEnum.ORDERDETAIN_NOT_EXIT);
        }
        OrderMaster orderMaster = orderMasterRepository.findOne(orderId);
        if(orderMaster == null)
        {
            throw new SellException(ResultEnum.ORDER_NOT_EXIT);
        }
        OrderDto orderDto = new OrderDto();
        BeanUtils.copyProperties(orderMaster,orderDto);
        orderDto.setOrderDetails(orderDetailList);
        return  orderDto;
    }

    /**查询订单列表
     * @param buyerOpenid 用户openid
     * @param pageable 分页对象
     * @return 分页信息
     */
    @Override
    @Transactional
    public Page<OrderDto> findOrderList(String buyerOpenid, Pageable pageable) {
       //  通过用户的openid 查找所有的order 并进行分页展示 接下来还要通过转化为dto对象 商品详情不用转化
       Page<OrderMaster> orderMasters = orderMasterRepository.findByBuyerOpenid(buyerOpenid,pageable);
       List<OrderDto> orderDtoList = OrderMaster2OrderDtoVConverter.converter(orderMasters.getContent());
       Page<OrderDto> orderDtoPage = new PageImpl<OrderDto>(orderDtoList,pageable,orderMasters.getTotalElements());
        return orderDtoPage;
    }
    /**
     * 取消订单
     * @param orderDto 订单dto
     * @return 订单dto
     */
    @Override
    @Transactional
    public OrderDto cancel(OrderDto orderDto) {
        List<CartDto> cartDtoList = new ArrayList<>();
        // 1. 判断订单的状态 是新订单才可支持取消订单 如果是已经完结的订单不支持取消 或者退款

        if(!orderDto.getOrderStatus().equals(OrderStatusEnum.NEW.getCode()))
         {
             throw new SellException(ResultEnum.ORDER_NOT_EXIT);
         }
        // 2. 更改订单状态
         OrderMaster orderMaster = new OrderMaster();
         orderDto.setOrderStatus(OrderStatusEnum.CANCLE.getCode());
        BeanUtils.copyProperties(orderDto,orderMaster);
        orderMaster.setOrderId(orderDto.getOrderId());
        orderMasterRepository.save(orderMaster);
        //3. 如果已经付款 需要退款给用户
         if(orderDto.getPayStatus().equals(PayStatusEnum.SUCCESS.getCode()))
         {
           payService.refund(orderDto);
         }
        //4. 返回库存
        if(CollectionUtils.isEmpty(orderDto.getOrderDetails()))
        {
            logger.error("[取消订单] orderDto={}", JsonUtils.toJson(orderDto));
            throw new SellException(ResultEnum.ORDER_NOT_EXIT);
        }
        //CartDto cartDto = new CartDto();
        cartDtoList = orderDto.getOrderDetails().stream().map(e -> new CartDto(e.getProductId(),e.getProductQuantity()))
                .collect(Collectors.toList());
       productService.increseStock(cartDtoList);

      return orderDto;


    }

    @Override
    @Transactional
    public OrderDto finishi(OrderDto orderDto) {
        if(!orderDto.getOrderStatus().equals(OrderStatusEnum.NEW.getCode()))
        {
            logger.error("[完结订单]完结订单{}",orderDto);
            throw new SellException(ResultEnum.ORDERSTARUS_NOT_CORRECT);
        }
        orderDto.setOrderStatus(OrderStatusEnum.FINISHIED.getCode());
        OrderMaster orderMaster = new OrderMaster();
        BeanUtils.copyProperties(orderDto,orderMaster);
        orderMasterRepository.save(orderMaster);
        return orderDto;

    }

    @Override
    @Transactional
    public OrderDto paid(OrderDto orderDto) {
        //  判断如果订单状态不等于 新订单的话 抛出异常
       if(!orderDto.getOrderStatus().equals(OrderStatusEnum.NEW.getCode()))
       {
           logger.error("[支付订单]orderDto{}",orderDto);
           throw new SellException(ResultEnum.ORDERSTARUS_NOT_CORRECT);
       }
        //  判断支付状态
        if(!orderDto.getPayStatus().equals(PayStatusEnum.WAIT.getCode()))
        {
            logger.error("[支付订单]支付订单{}",orderDto);
            throw new SellException(ResultEnum.PAID_STATUS_NOT_CORRECT);
        }
        orderDto.setPayStatus(PayStatusEnum.SUCCESS.getCode());
        OrderMaster orderMaster = new OrderMaster();
        BeanUtils.copyProperties(orderDto,orderMaster);
        orderMasterRepository.save(orderMaster);
        return orderDto;
    }
}
